# plugs/core.py
#
#

""" core bot commands """

__copyright__ = 'this file is in the public domain'

from gozerbot.generic import getwho, die, reboot
from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.callbacks import callbacks
from gozerbot.redispatcher import rebefore, reafter
from gozerbot.plugins import plugins
from gozerbot.users import users
from gozerbot.partyline import partyline
from gozerbot.fleet import fleet
from gozerbot.config import config
from gozerbot.statdict import Statdict
from gozerbot.aliases import aliases, aliasreverse
from gozerbot.plughelp import plughelp
if not config['dbenable']:
    from plugs.infoitem import info
    from plugs.quote import quotes
    from plugs.karma import karma
    from plugs.todo import todo
else:
    from dbplugs.infoitem import info
    from dbplugs.quote import quotes
    from dbplugs.karma import karma
    from dbplugs.todo import todo
from plugs.shop import shops
from gozerbot.aliases import aliases
import time, threading, sys

plughelp.add('core', 'core commands for the bot')

def handle_userhostcache(bot, ievent):
    """ show bots userhost cache """
    ievent.reply(bot.userhosts)

cmnds.add('userhostcache', handle_userhostcache, 'OPER')

def handle_list(bot, ievent):
    """ list [<plugin>] .. list loaded plugins or list commands provided by \
        plugin """
    plugslist = plugins.list()
    try:
        what = ievent.args[0]
    except:
        # no arguments given .. show plugins
        result = []
        for i in plugslist:
            result.append(i.split('.')[-1])
        result.sort()
        ievent.reply('we have the following plugins: %s' %  \
' .. '.join(result))
        return
    # show commands of <what> plugin
    result = []
    for i, j in cmnds.items():
        if what == j.plugname:
            result.append(i)
    if result:
        result.sort()
        ievent.reply('%s has the following commands: %s' % \
(what, ' .. '.join(result)))
    else:
        ievent.reply('no commands found for plugin %s' % what)

cmnds.add('list', handle_list, ['USER', 'WEB'])
examples.add('list', 'list registered plugins or list commands in \
plugin', '1) list 2) list rss')

def handle_available(bot, ievent):
    """ available .. show what plugins are available """
    ievent.reply('available plugins: ' + ' ' .join(plugins.available()))

cmnds.add('available', handle_available, 'USER')
examples.add('available', 'show what plugins are available', 'available')
aliases.data['avail'] = ' available'

def doquit(bot, ievent):
    """ quit .. quit the bot """
    try:
        backupstop = 1
        fleet.exitall()
        plugins.exit()
        time.sleep(1)
    finally:
        die()

cmnds.add('quit', doquit, 'OPER')
examples.add('quit', 'quit the bot', 'quit')

def handle_reboot(bot, ievent):
    """ reboot .. reboot the bot """
    try:
        backupstop = 1
        fleet.exitall()
        plugins.exit()
        time.sleep(1)
    finally:
        reboot()

cmnds.add('reboot', handle_reboot, 'OPER')
examples.add('reboot', 'restart the bot', 'reboot')

def handle_commands(bot, ievent):
    """ commands [<permission>] .. show commands allowed by permission .. \
        default permission is 'USER' """
    try:
        what = ievent.args[0].upper()
    except IndexError:
        what = 'USER'
    cmndlist = cmnds.list(what)
    cmndlist.sort()
    if cmndlist:  
        ievent.reply('i have the following commands for the %s permission:\
 %s' % (what, ' '.join(cmndlist)))
    else:
        ievent.reply("can't find any command for permission %s" % what)

cmnds.add('commands', handle_commands, ['USER', 'WEB'])
examples.add('commands', 'show commands allowed for [<permission>]', '1) \
commands 2) commands OPER')

def handle_perm(bot, ievent):
    """ perm <command> .. get permission of command """
    try:
        cmnd = ievent.args[0]
    except IndexError:
        ievent.reply("perm <cmnd>")
        return
    try:
        cmnd = aliases.data[cmnd]
    except KeyError:
        pass
    perms = cmnds.perms(cmnd)
    if perms:
        ievent.reply("%s command needs %s permission" % (cmnd, perms))
        return
    ievent.reply("can't find perm for %s" % cmnd)

cmnds.add('perm', handle_perm, ['USER', 'WEB'])
examples.add('perm', 'show permission of command', 'perm quit')

def handle_cc(bot, ievent):
    """ cc [<controlchar>] .. set/get control character of channel """
    chan = ievent.channel
    try:
        what = ievent.args[0]
        if not users.allowed(ievent.userhost, 'OPER'):
            return
        if len(what) > 1:
            ievent.reply("only one character is allowed")
            return
        try:
            bot.channels[chan]['cc'] = what
        except KeyError:
            ievent.reply("no channel %s in database")
            return
        except TypeError:
            ievent.reply("no channel %s in database" % chan)
            return
        bot.channels.save()
        ievent.reply('control char set to %s' % what)
    except IndexError:
        # no argument given .. show cc of channel command is given in
        try:
            cchar = bot.channels[chan]['cc']
            ievent.reply('control character for channel %s is %s' % \
(chan,cchar))
        except KeyError:
            ievent.reply("default cc is !")
        except TypeError:
            ievent.reply("default cc is !")

cmnds.add('cc', handle_cc, 'USER')
examples.add('cc', 'set control char of channel or show control char of \
channel','1) cc # 2) cc')

def handle_intro(bot, ievent):
    """ intro <nick> .. do whois on nick to sync userhosts cache """
    try:
        who = ievent.args[0]
    except IndexError:
        ievent.reply("intro <nick>")
        return
    bot.whois(who)
    ievent.reply('whois command send')

cmnds.add('intro', handle_intro, 'OPER')
examples.add('intro', 'intro <nick>', 'intro dunker')

def handle_loglevel(bot, ievent):
    """ loglevel <level> .. get or set loglevel .. the lower the more the \
        bot logs """
    if len(ievent.args) == 0:
        handle_loglevel2(bot, ievent)
        return
    try:
        level = int(ievent.args[0])
    except IndexError:
        ievent.reply('i need a loglevel argument')
        return
    except ValueError:
        ievent.reply('i need a integer argument')
        return
    config.set('loglevel', level)
    ievent.reply('loglevel is now %s' % config['loglevel'])

def handle_loglevel2(bot, ievent):
    """ show loglevel """
    ievent.reply('loglevel is %s' % config['loglevel'])

cmnds.add('loglevel', handle_loglevel,'OPER')
examples.add('loglevel', 'get/set current loglevel', '1) loglevel 2) \
loglevel 0')

def handle_more(bot, ievent):
    """ more [<nick>] .. show cached data """
    try:
        who = ievent.args[0]
    except IndexError:
        who = ievent.nick 
    # see if we can get cached data .. pop returns 1 line
    txt = bot.more.pop(who)
    if txt:
        # yup got it
        moresize = bot.more.size(who)
        if moresize > 0:
            txt += " (+%s)" % moresize
        if ievent.msg:
            bot.output(ievent.nick, txt, 'msg')
        else:
            bot.output(ievent.channel, txt, 'msg')
    else:
        ievent.reply('no more data available for %s' % who)

cmnds.add('more', handle_more, 'USER')
examples.add('more', 'show bot output that has been buffered', '1) more 2) \
more dunk')

def handle_partylist(bot, ievent):
    """ partylist .. show users on partylist """
    partynicks = partyline.list_nicks()
    if partynicks:
        ievent.reply("people on partyline = " + ' '.join(partynicks))
    else:
        ievent.reply('no party yet!')

cmnds.add('partylist', handle_partylist, ['USER', 'WEB'])
examples.add('partylist', 'show connected partylist users', 'partylist')

def handle_running(bot, ievent):
    """ running .. show running threads """
    stats = Statdict()
    threadlist = threading.enumerate()
    for thread in threadlist:
        stats.upitem(thread.getName())
    txt = ""
    for item in stats.top():
        txt += "%s = %s " % (item[0], item[1])
    ievent.reply(txt)

cmnds.add('running', handle_running, ['USER', 'WEB'])
examples.add('running', 'show from which files threads are running', 'running')

def handle_save(bot, ievent):
    """ save .. save data to disk """
    ievent.reply('saving ..')
    plugins.save()
    fleet.save()
    config.save()
    ievent.reply('done')

cmnds.add('save', handle_save, 'OPER')
examples.add('save', 'save bot data', 'save')

def handle_size(bot, ievent):
    """ size .. show size of core datastructures """
    txt = ""
    txt += "users: %s " % str(users.size())
    txt += "cmnds: %s " % str(cmnds.size())
    txt += "callbacks: %s " % str(callbacks.size())
    txt += "rebefore: %s " % str(rebefore.size())
    txt += "reafter: %s " % str(reafter.size())
    txt += "aliases: %s " % str(len(aliases.data))
    txt += "examples: %s " % str(examples.size()) 
    txt == "infoitems: %s " % str(info.size())
    txt += "quotes: %s " % str(quotes.size())
    txt += "karma: %s " % str(karma.size())
    txt += "todo: %s " % str(todo.size())
    txt += "shop: %s " % str(len(shops.data))
    ievent.reply(txt)

cmnds.add('size', handle_size, ['USER', 'WEB'])
examples.add('size', 'show sizes of various data structures', 'size')

def handle_version(bot, ievent):
    """ version .. show bot's and python's version """
    sysversion = sys.version.replace('\n','') # python version
    ievent.reply("%s running on python %s" % (config['version'], \
sysversion))

cmnds.add('version', handle_version, ['USER', 'WEB'])
examples.add('version', 'show version of the bot', 'version')
aliases.data['v'] = 'version'

def handle_whereis(bot, ievent):
    """ whereis <cmnd> .. locate a command """
    try:
        cmnd = ievent.args[0]
    except IndexError:
        ievent.reply('whereis <cmnd>')
        return
    plugs = plugins.whereis(cmnd)
    if plugs:
        ievent.reply("%s command is in %s" %  (cmnd, str(plugs)))
    else:
        ievent.reply("can't find " + cmnd)

cmnds.add('whereis', handle_whereis, ['USER', 'WEB'])
examples.add('whereis', 'whereis <cmnd> .. show in which plugins <what> \
is', 'whereis test')

def handle_help(bot, ievent):
    """ help [<cmnd>|<plugin>] .. show help on plugin/command or show \
        basic help msg  """
    try:
        what = ievent.args[0]
    except IndexError:
        ievent.reply('help <cmnd> or help <plugin> .. see the !available \
command for a list of available plugins')
        return
    phelp = plughelp.get(what)
    cmndresult = []
    if phelp:
        ievent.reply('plugin description: %s' % phelp)
        perms = users.getperms(ievent.userhost)
        for i, j in cmnds.iteritems():
            if what == j.plugname:
                for perm in j.perms:
                    if perm in perms:                
                        cmndresult.append(i)
        if cmndresult:
            cmndresult.sort()
            resultstr = ""
            for i in cmndresult:
                alias = aliasreverse(i)
                if alias:
                    resultstr += "%s (%s) .. " % (i, alias)
                else:
                    resultstr += "%s .. " % i
            ievent.reply('commands: %s'\
 % resultstr[:-4])
        else:
            ievent.reply('no commands available for permission %s' % \
str(perms))
        result = []
        for i in rebefore:
            if what == i.plugname:
                if users.allowed(ievent.userhost, i.perms):
                    result.append(i.regex)
        for i in reafter:
            if what == i.plugname:
                if users.allowed(ievent.userhost, i.perms):
                    result.append(i.regex)
        if result:
            resultstr = ""
            for i in result:
                resultstr += '"%s" .. ' % i
            ievent.reply('regular expressions: %s' % resultstr[:-4])
        else:
            pass
        result = []
        for i, j in callbacks.items():
            for z in j:
                if what == z.plugname:
                    result.append(i)
        if result:
            resultstr = ""
            for i in result:
                resultstr += "%s .. " % i
            ievent.reply('callbacks: %s' % resultstr[:-4])
        else:
            pass
        if not cmndresult:
            return
    isalias = 0
    if what in aliases.data:
        ievent.reply('%s is an alias for %s' % (what, aliases.data[what]))
        what = aliases.data[what]
    try:
        example = examples[what]
    except KeyError:
        return
    ievent.reply('command description of %s: %s .. alias: %s .. examples:\
 %s' % (what, example.descr, aliasreverse(what), example.example))

cmnds.add('help', handle_help, ['USER', 'WEB'])
examples.add('help', 'get help on <cmnd> or <plugin>', '1) help test 2) \
help misc')

def handle_apro(bot, ievent):
    """ apro <cmnd> .. apropos for command """
    try:
        what = ievent.args[0]
    except:
        ievent.reply('apro <what>')
        return
    result = ""
    teller = 1
    for i in cmnds.apropos(what):
        result += '%s) %s ' % (str(teller), i)
        teller += 1
    result += 'aliases: '
    got = teller
    for i in aliases.data.keys():
        if what in i:
            result += '%s) %s ' % (teller, i)
            teller += 1
    if teller == got:
        result = result[:-9]
    if result:
        ievent.reply(result)
    else:
        ievent.reply('no matching commands found for %s' % what)

cmnds.add('apro', handle_apro, ['USER', 'WEB'])
cmnds.add('apropos', handle_apro, 'USER')
examples.add('apro', 'apro <what> .. search for commands that contain \
<what>', 'apro com')

def handle_u(bot, ievent):
    """ u <nick> .. show userhost entry in cache """
    try:
        nick = ievent.args[0]
    except:
        ievent.reply('u <nick>')
        return
    result = getwho(bot, nick)
    if result:
        ievent.reply(result)
    else:
        ievent.reply("can't get userhost for %s" % nick)

cmnds.add('u', handle_u, 'USER')
examples.add('u', 'u <nick> .. get userhost cache entry for <nick>', \
'u dunker')
